Home / Community / Blog

Zgłębiam temat rozpoczęty ostatnio. Wyszukuję za pomocą wbudowanej funkcji advancedsearch. Formatkę wyszukiwania, a w zasadzie jej pola, można zrobić tak jak podano w przykładzie (strona nie jest już rozwijana, ale przykład działa). Ma to ten minus, że atrybuty trzeba wstawić po ich ID, a nie nazwie, ale odpowiednio komentując kod można go zrobić przejżystym.

W mojej wersji zrobiłem wyszukiwanie po atrybutach o ID 362 i 363 (każdy się domyśli, że wyszukuję po Miejscowości i powiecie :-) . Wstawiłem w jednym z własnych szablonów (template) taki kod:

<form action={"/content/advancedsearch/"|ezurl} method="get">
    {* 45, czyli Atrakcja *}
    <input type="hidden" name="SearchContentClassID" value="45" />
    {* 363 - Powiat *}
    Powiat: <input type="hidden"
name="Content_search_attribute_fulltext_classattribute_id[]"
value="363" />
    <input type="text"
name="Content_search_attribute_fulltext_value[]"
value="" />
    {* 362 Miejscowość (attraction_attrib_city) *}
    Miasto: <input type="hidden"
name="Content_search_attribute_fulltext_classattribute_id[]"
value="362" />
    <input type="text"
name="Content_search_attribute_fulltext_value[]"
value="" />

    <input type="submit" value="Search" name="SearchButton">
</form>

To nawet działa, trzeba tylko pamiętać o ustawieniu

[SearchSettings]
AllowEmptySearch=enabled

w pliku settings/override/site.ini.append.php, ew. można jeszcze dołożyć w tej samej sekcji

EnableWildcard=true

, ale to wymagane tylko dla zaawansowanych użytkowników.

Teraz wystarczy tylko ustalić jak zrobić własną stronę z własnym szablonem na którym będzie tylko wyszukiwanie. Można oczywiście utworzyć własną klasę, nawet nie musi mieć atrybutów - wystarczy, że będzie miała nazwę, którą będzie można powiązać z szablonem zawierającym wyłącznie formularz wyszukiwania, ale może można to zrobić prościej.

Zadanie wydawałoby się dość proste - zrobić wyszukiwanie po atrybutach klasy np. Znaleźć te obiekty klasy atrakcja gdzie miasto (attraction_attrib_city) jest równe Gdynia. Przy czym wartości ma sobie użytkownik podawać.

Pierwsze poszukiwania wskazywały na ezFind, ale to rozszerzenie jest dostępne tylko komercyjnie.

Innym tropem jest funkcja fetch, ale jak stworzyć dla niej formatkę do wprowadzania parametrów wyszukiwania na razie nie mam pojęcia.

Po stworzeniu własnej klasy wypadało by ją ładnie wyświetlać. Jako, że moja klasa dziedziczyła po klasie Artykuł naturalne jest, że jako wzór do modyfikacji wybrałem plik article.tpl z katalogu design/base/override/templates/full na podstawie którego utworzyłem plik attraction.tpl w katalogu design/wlasne/override/templates/full.

W tym, nowo utworzonym pliku przed linią wyświetlającą komentarze użytkowników:

<div class="attribute-tipafriend">

wstawiłem dwa pierwsze dodane atrybuty:

{* Adres *}
<div class="attribute-short">
    <p>Adres</p>
</div>
<div class="attribute-long">
    {attribute_view_gui attribute=$node.data_map.attraction_attrib_address}
</div>

{* Kontakt *}
<div class="attribute-short">
    <p>Kontakt</p>
</div>
{if $node.data_map.attraction_attrib_contact.content.is_empty|not}
    <div class="attribute-long">
        {attribute_view_gui attribute=$node.data_map.attraction_attrib_contact}
    </div>
{/if}

dzięki temu na stronie wyświetlają się dodatkowo (poza tym co w standardowym artykule) adres atrakcji i dane kontaktowe.

Stworzyłem sobie nową klasę (jako kopię klasy Article) i nazwałem ją Atrakcja (attraction). Niestety wygląd nie zachwycał - wartości atrybutów były w kolejnych wierszach jeden za drugim, bez żadnych dodatkowych informacji. Trzeba przygotować dla niej nowy szablon.

Zgodnie ze starymi notatkami aby nie mieszać własnych szablonów z tymi domyślnymi dołożyłem nowy katalog w katalogu design i nazwałem go własne po czym podpiąłem go jako źródło szablonów dopisując

[DesignSettings]
SiteDesign=ezwebin
AdditionalSiteDesignList[]
AdditionalSiteDesignList[]=wlasne
AdditionalSiteDesignList[]=base

w pliku settings/siteaccess/pol/site.ini.append.php. Dlatego w pol, bo był ustawiony jako domyślny

[SiteSettings]
DefaultAccess=pol

w pliku settings/override/site.ini.append.php. Teraz utworzyłem plik design/wlasne/override/templates/full/attraction.tpl gdzie będzie się miał znajdować szablon opisujący wygląd obiektów tej klasy.

Teraz wystarczyło przekonać system, żeby korzystał z tego szablonu. Zgodnie z dokumentacją dopisałem

[full_attraction]
Source=node/view/full.tpl
MatchFile=full/attraction.tpl
Subdir=templates
Match[class_identifier]=attraction

do pliku settings/override/override.ini.append.php który wcześniej utworzyłem na wzór innych.

Teraz trzeba by wypełnić plik attraction.tpl, ale o tym w następnym odcinku ...

Standardowo po instalacji linki w ez Publish'u wyglądają jakoś tak:

http://www.jaqb.int.pl/index.php?/pol/Spolecznosc/Blog

ale ten index.php w środku niezbyt ładnie wygląda. Żeby się go pozbyć trzeba zmienić definicję wirtualnego serwera zgodnie z instrukcją na stronie (ja dopisałem tylko sekcję dotyczącą mod_rewrite do istniejących wpisów), zmodyfikować plik

settings/override/site.ini.append.php

dodając w sekcji SiteAccessSettings wiersz:

ForceVirtualHost=true

oraz wyczyścić pamięć tymczasową (cache)

php ./bin/php/ezcache.php --clear-all 

od wersji 4.4 trzeba dodać jeszcze --allow-root-user gdy robimy to jako użytkownik root.

Po tym jak i naprawiłem tagi (jak się okazało nie do końca) i zaczęło działać archiwum blogów naprawienie wyszukiwania wpisów na blogu po tagach było dość proste. Błąd pojawiający się w var/log/error.log

AND ezkeyword_attribute_link.keyword_id = ezkeyword.id \
ORDER BY a0.sort_key_int DESC LIMIT 10
BŁĄD:  dla SELECT DISTINCT, ORDER BY wyrażenia muszą występować \
na liście wyboru

(a w zasadzie końcówka zapytania) oprowadziła mnie do pliku kernel/content/ezcontentfunctioncollection.php w którym zmodyfikowałem zapytanie SQL rozpoczynające się w linii 989 i kończące się jak w błędzie powyżej. Najpierw z listy sortowania wyciągam same nazwy pól i dodaję je do zapytania. Cała zmiana wygląda tak:

--- ezcontentfunctioncollection.php-org    2009-02-16 16:16:49.000000000 +0100
+++ ezcontentfunctioncollection.php-new    2011-02-14 00:01:11.000000000 +0100
@@ -993,8 +993,12 @@
  {
  $sqlMatching = "ezkeyword.keyword = '$alphabet'";
  }
+ if (substr( $sqlTarget, 0, 9) == 'DISTINCT ') {
+ $sortingFielsdList=", ".str_replace(array("ASC", "DESC"), "", \
$sortingInfo['sortingFields']);
+ }

  $query = "SELECT $sqlTarget
+ {$sortingFielsdList}
  FROM ezkeyword,
  ezkeyword_attribute_link,ezcontentobject_tree,ezcontentobject, \
ezcontentclass
  $sortingInfo[attributeFromSQL]
  $sqlPermissionChecking[from]

Teraz żadne błędy się już nie pojawiają, ale i tak chyba czas pomyśleć i aktualizacji.

W istniejącej instalacji ezPublish w wersji 4.0.3 miałem problem, o nie wyświetlała się chmura tag'ów (tag cloud). Wskazówka była w pliku var/log/error.log:

Error: error executing query: SELECT ezkeyword.keyword, count(*) as keyword_count
 FROM ezkeyword,
  ezkeyword_attribute_link,
   ezcontentobject,
   ezcontentobject_attribute,
   ezcontentobject_tree
                                            
   WHERE ezkeyword.id = ezkeyword_attribute_link.keyword_id
    AND ezkeyword_attribute_link.objectattribute_id = ezcontentobject_attribute.id
    AND ezcontentobject_attribute.contentobject_id = ezcontentobject_tree.contentobject_id
    AND ezcontentobject_attribute.contentobject_id = ezcontentobject.id
    AND ezcontentobject.status = 1
    AND ezcontentobject_attribute.version = ezcontentobject.current_version
    AND ezcontentobject_tree.main_node_id = ezcontentobject_tree.node_id
    AND ezcontentobject_tree.path_string like '/1/2/%'
    AND ezcontentobject_tree.node_id != 2
                                            
    AND ezcontentobject_tree.is_invisible = 0
                                            
    AND ezcontentobject.language_mask & 3 > 0 

   GROUP BY ezkeyword.id
   ORDER BY ezkeyword.keyword ASC BŁĄD:  kolumna "ezkeyword.keyword"
musi występować w klauzuli GROUP BY lub być użyta w funkcji agregującej

rozwiązanie jest oczywiste, mniej oczywista jest lokalizacja pliku w którym jest zdefiniowane to zapytanie. Przeszukałem pliki pod kątem frazy ezkeyword.keyword i znalazłem plik

extension/ezwebin/autoloads/eztagcloud.php

w którym zmieniłem GROUP BY'a w linii 120 na:

GROUP BY ezkeyword.id, ezkeyword.keyword

problem został rozwiazany, a efekty było widać nawet bez czyszczenia pamięci podręcznej.

Pojawiał się błąd:

BŁĄD:  błąd składni w lub blisko "DESC"
LINE 14: ... FROM_UNIXTIME( ezcontentobject_attribute.data_int
) ) DESC

Żeby to poprawić to najpierw trzeba dodać funkcje które udają (emulują) MySQL'a (źródło):

CREATE OR REPLACE FUNCTION MONTH(TIMESTAMP without TIME ZONE)
RETURNS INTEGER AS $$ 
      SELECT EXTRACT(MONTH FROM $1)::INTEGER; 
$$ LANGUAGE SQL IMMUTABLE;

CREATE OR REPLACE FUNCTION MONTH(TIMESTAMP WITH TIME ZONE)
RETURNS INTEGER
AS $$
      SELECT EXTRACT(MONTH FROM $1)::INTEGER;
$$ LANGUAGE SQL STABLE;
CREATE OR REPLACE FUNCTION MONTH(DATE) RETURNS INTEGER
AS $$
      SELECT EXTRACT(MONTH FROM $1)::INTEGER;
$$ LANGUAGE SQL IMMUTABLE;

dodatkowo jeszcze:

CREATE OR REPLACE FUNCTION YEAR(TIMESTAMP without TIME ZONE)
RETURNS INTEGER AS $$ 
      SELECT EXTRACT(YEAR FROM $1)::INTEGER; 
$$ LANGUAGE SQL IMMUTABLE;

oraz konwersji czasu (źródło):

CREATE OR REPLACE FUNCTION from_unixtime(integer)
RETURNS timestamp AS '
 SELECT
 $1::abstime::timestamp without time zone AS result
 ' LANGUAGE 'SQL';

CREATE OR REPLACE FUNCTION unix_timestamp() RETURNS integer AS '
 SELECT
 ROUND(EXTRACT( EPOCH FROM abstime(now()) ))::int4 AS result;
 ' LANGUAGE 'SQL';

CREATE OR REPLACE FUNCTION unix_timestamp(timestamp with time zone)
RETURNS integer AS '
 SELECT
 ROUND(EXTRACT( EPOCH FROM ABSTIME($1) ))::int4 AS result;
 ' LANGUAGE 'SQL';

i na podstawie powyższych:

CREATE OR REPLACE FUNCTION unix_timestamp(text)
 RETURNS integer AS '
 SELECT
 ROUND(EXTRACT( EPOCH FROM ABSTIME($1) ))::int4 AS result;
 ' LANGUAGE 'SQL';

i na koniec:

CREATE OR REPLACE FUNCTION "concat"(int, text, int, text, int)
 RETURNS text AS '
 SELECT $1 || $2 || $3 || $4 || $5;
 ' LANGUAGE 'sql';

specjalnie dla zapytania w pliku extension/ezwebin/autoloads/ezarchive.php które też trzeba poprawić. W zapytaniu SQL w linii 54 jest błąd: GROUP BY nie służy do sortowania a poza tym skoro pola są zdefiniowane i nazwane to wystarczy użyć tej nazwy. Ja zmieniłem końcówkę na taką:

GROUP BY year, month
ORDER BY year DESC, month DESC

niestety na tym nie koniec. Pojawiają się kolejne błędy, ale o tym w następnym odcinku ...

Bieżąca linia ez Publish nie zawiera eksportu do PDF. Zamiennikiem wycofanego eZPDF może być paradoxPDF.

W ez Publish 4.4, umieszczonym na stronie utrzymywanej przez 1and1 dostawałem błąd "Data error" zamiast listy obiektów podrzędnych. Rozwiązaniem jest zmiana linii 923 pliku lib/ezutils/classes/ezsys.php z:

$isCGI = ( substr( php_sapi_name(), 0, 3 ) == 'cgi' );

na

$isCGI = false;

Ten błąd został (podobno) już poprawiony w wersji 4.5.

Just my blog...

Mon Tue Wed Thu Fri Sat Sun
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31